/**************************************************************************** 
 * Meta，一个轻量级的静态分区Hypervisor 
 *
 * 版权(c) , 2022-
 *
 * 作者:
 *      Tupelo Shen <shenwanjiang2013@163.com>
 *
 * Meta是一个自由软件，你可以在遵循GNU GPLv2协议的条件下，重新修改并发布它。
 *
 ***************************************************************************/

#include <cache.h>

/****************************************************************************
 ****                       变量声明                                     ****
 ****************************************************************************/
static struct cache cache_dscr;

size_t COLOR_NUM = 1;
size_t COLOR_SIZE = 1;

/****************************************************************************
 ****                       私有函数接口                                 ****
 ****************************************************************************/
static void cache_calc_colors( struct cache* dscrp, size_t page_size);

/****************************************************************************
 ****                       公共函数定义                                 ****
 ****************************************************************************/
/**
 * 功能描述: 
 * 入口参数: 
 * 出口参数: void
 * 返 回 值: void
 * 修改日期: 2022-09-21
 */
void cache_enumerate()
{
    cache_arch_enumerate(&cache_dscr);
    cache_calc_colors(&cache_dscr, PAGE_SIZE);
}

/****************************************************************************
 ****                       私有函数定义                                 ****
 ****************************************************************************/

/**
 * 功能描述: 按照page_size对cache进行染色
 * 入口参数: dscrp:     指向保存cache信息的数据结构的指针
 *           page_size: 页大小
 * 出口参数: dscrp:     指向保存cache信息的数据结构的指针
 * 返 回 值: void
 * 修改日期: 2022-09-21
 */
static void cache_calc_colors( struct cache* dscrp, size_t page_size)
{
    if (dscrp->lvls == 0) {
        /* No cache? */
        return;
    }

    size_t llc = dscrp->min_shared_lvl;

    if ((dscrp->type[llc] != UNIFIED) || (dscrp->indexed[llc][0] != PIPT))
        return;

    size_t llc_way_size =
        dscrp->numset[llc][UNIFIED] * dscrp->line_size[llc][UNIFIED];

    size_t flc_way_size = 0;
    if ((dscrp->type[0] != UNIFIED)) {
        flc_way_size = dscrp->numset[0][0] * dscrp->line_size[0][0];
        size_t flc_i_way_size = dscrp->numset[0][1] * dscrp->line_size[0][1];
        if (((dscrp->indexed[0][0] == PIPT) ||
             (flc_i_way_size < flc_way_size)) &&
            (dscrp->indexed[0][1] == PIPT)) {
            flc_way_size = flc_i_way_size;
        }
    }

    size_t llc_num_colors = llc_way_size / page_size;
    size_t flc_num_colors = flc_way_size / page_size;

    COLOR_SIZE = flc_num_colors;
    COLOR_NUM = llc_num_colors / COLOR_SIZE;
}